<?php

namespace app\api\controller;

use app\common\model\Help;
use think\Controller;
use think\Request;
use think\Db;
use think\facade\Validate;
use app\api\model\SystemMenus;

class Menu extends Controller
{
    /**
     * 获取菜单列表
     */
    public function index(Request $request)
    {
        try {
            $param = $request->param();
            if ($param) {
                $params = $param['params'] ?? [];
            }

            if (empty($params['business'])) {
                $params['business'] = 'admin';
            }

            // 构建查询条件
            $where = [];
            if (!empty($params['status'])) {
                $where[] = ['status', '=', $params['status']];
            }
            if (!empty($params['cache_status'])) {
                $where[] = ['cache_status', '=', $params['cache_status']];
            }

            if (!empty($params['business'])) {
                $where[] = ['business', 'like', '%' . $params['business'] . '%'];
            }


            // 先查询所有菜单
            $allMenus = Db::name('system_menus')
                ->order('sort ASC, id ASC')->where($where)
                ->select();

            // 如果有标题过滤
            if (!empty($params['title'])) {
                // 1. 找到所有匹配标题的菜单ID
                $matchedIds = [];
                foreach ($allMenus as $menu) {
                    if (stripos($menu['title'], $params['title']) !== false) {
                        $matchedIds[] = $menu['id'];
                    }
                }

                if (empty($matchedIds)) {
                    return []; // 没有匹配的菜单
                }


                // 2. 获取所有相关的菜单ID（匹配的菜单 + 所有父级 + 所有子级）
                $relatedIds = $this->getAllRelatedMenuIds($allMenus, $matchedIds);

                // 3. 过滤出相关的菜单
                $filteredMenus = [];
                foreach ($allMenus as $menu) {
                    if (in_array($menu['id'], $relatedIds)) {
                        $filteredMenus[] = $menu;
                    }
                }

                // 4. 构建树形结构
                $tree = $this->buildTree($filteredMenus);
            } else {
                // 没有过滤条件，直接构建完整树
                $tree = $this->buildTree($allMenus);
            }


            return json([
                'code' => 200,
                'message' => 'success',
                'data' => $tree
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '获取菜单列表失败：' . $e->getMessage()
            ]);
        }
    }


    /**
     * 获取菜单详情
     */
    public function read()
    {
        $id = input("id") ?? '';
        try {
            $menu = Db::name('system_menus')->where('id', $id)->find();

            if (!$menu) {
                return json([
                    'code' => 404,
                    'message' => '菜单不存在'
                ]);
            }

            return json([
                'code' => 200,
                'message' => 'success',
                'data' => $menu
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '获取菜单详情失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 新增菜单
     */
    public function save(Request $request)
    {
        try {
            $data = $request->param();

            // 验证数据
            $validate = $this->getValidate();
            if (!$validate->check($data)) {
                return json([
                    'code' => 400,
                    'message' => $validate->getError()
                ]);
            }

            // 处理数据
            $insertData = [
                'business' => $data['business'],
                'title' => $data['title'],
                'pid' => $data['pid'] ?? 0,
                'type' => $data['type'],
                'is_link' => $data['is_link'] ? 1 : 0,
                'link_url' => $data['link_url'] ?? '',
                'link_param' => $data['link_param'] ?? '',
                'components_url' => $data['components_url'] ?? '',
                'permission' => $data['permission'] ?? '',
                'cache_status' => $data['cache_status'],
                'icon' => $data['icon'] ?? '',
                'sort' => $data['sort'] ?? 0,
                'status' => $data['status'],
                'create_time' => time(),
                'update_time' => time()
            ];

            $id = Db::name('system_menus')->insertGetId($insertData);

            $help = new Help();
            $help->system_log($data, '新增菜单');

            return json([
                'code' => 200,
                'message' => '新增成功',
                'data' => ['id' => $id]
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '新增菜单失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 更新菜单
     */
    public function update(Request $request)
    {
        try {
            $data = $request->param();
            $id = $data['id'];

            // 检查菜单是否存在
            $menu = Db::name('system_menus')->where('id', $id)->find();
            if (!$menu) {
                return json([
                    'code' => 404,
                    'message' => '菜单不存在'
                ]);
            }

            // 验证数据
            $validate = $this->getValidate();
            if (!$validate->check($data)) {
                return json([
                    'code' => 400,
                    'message' => $validate->getError()
                ]);
            }

            // 处理数据
            $updateData = [
                'business' => $data['business'],
                'title' => $data['title'],
                'pid' => $data['pid'] ?? 0,
                'type' => $data['type'],
                'is_link' => $data['is_link'] ? 1 : 0,
                'link_url' => $data['link_url'] ?? '',
                'link_param' => $data['link_param'] ?? '',
                'components_url' => $data['components_url'] ?? '',
                'permission' => $data['permission'] ?? '',
                'cache_status' => $data['cache_status'],
                'icon' => $data['icon'] ?? '',
                'sort' => $data['sort'] ?? 0,
                'status' => $data['status'],
                'update_time' => time()
            ];

            Db::name('system_menus')->where('id', $id)->update($updateData);


            $help = new Help();
            $help->system_log($data, '修改菜单');

            return json([
                'code' => 200,
                'message' => '更新成功'
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '更新菜单失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 删除菜单
     */
    public function delete()
    {
        $id = input("id") ?? '';
        try {
            // 检查菜单是否存在
            $menu = Db::name('system_menus')->where('id', $id)->find();
            if (!$menu) {
                return json([
                    'code' => 404,
                    'message' => '菜单不存在'
                ]);
            }

            // 检查是否有子菜单
            $childCount = Db::name('system_menus')->where('pid', $id)->count();
            if ($childCount > 0) {
                return json([
                    'code' => 400,
                    'message' => '请先删除子菜单'
                ]);
            }

            Db::name('system_menus')->where('id', $id)->delete();

            $help = new Help();
            $help->system_log($id, '删除菜单');

            return json([
                'code' => 200,
                'message' => '删除成功'
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '删除菜单失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 更新菜单状态
     */
    public function update_status(Request $request)
    {
        $id = input("id") ?? '';
        try {
            $status = $request->param('status');

            if (!in_array($status, [1, 2])) {
                return json([
                    'code' => 400,
                    'message' => '状态值不正确'
                ]);
            }

            // 检查菜单是否存在
            $menu = Db::name('system_menus')->where('id', $id)->find();
            if (!$menu) {
                return json([
                    'code' => 404,
                    'message' => '菜单不存在'
                ]);
            }

            Db::name('system_menus')->where('id', $id)->update([
                'status' => $status,
                'update_time' => time()
            ]);

            return json([
                'code' => 200,
                'message' => '状态更新成功'
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '更新状态失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 获取菜单树（用于下拉选择）
     */
    public function tree()
    {
        try {
            $menus = Db::name('system_menus')
                ->where('status', 1)
                ->field('id, title, pid, business')
                ->order('sort ASC, id ASC')
                ->select();

            $tree = $this->buildTree($menus);

            return json([
                'code' => 200,
                'message' => 'success',
                'data' => $tree
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '获取菜单树失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 获取所有相关的菜单ID（包括匹配的菜单、所有父级菜单、所有子级菜单）
     */
    private function getAllRelatedMenuIds($allMenus, $matchedIds)
    {
        $relatedIds = $matchedIds;

        // 获取所有父级菜单ID
        $parentIds = $this->getAllParentIds($allMenus, $matchedIds);
        $relatedIds = array_merge($relatedIds, $parentIds);

        // 获取所有子级菜单ID
        $childIds = $this->getAllChildIds($allMenus, $matchedIds);
        $relatedIds = array_merge($relatedIds, $childIds);

        return array_unique($relatedIds);
    }

    /**
     * 递归获取所有父级菜单ID
     */
    private function getAllParentIds($allMenus, $ids)
    {
        $parentIds = [];

        foreach ($allMenus as $menu) {
            if (in_array($menu['id'], $ids)) {
                // 如果当前菜单有父级，且父级不是0
                if ($menu['pid'] > 0) {
                    $parentIds[] = $menu['pid'];
                    // 递归获取父级的父级
                    $grandParentIds = $this->getAllParentIds($allMenus, [$menu['pid']]);
                    $parentIds = array_merge($parentIds, $grandParentIds);
                }
            }
        }

        return array_unique($parentIds);
    }

    /**
     * 递归获取所有子级菜单ID
     */
    private function getAllChildIds($allMenus, $ids)
    {
        $childIds = [];

        foreach ($allMenus as $menu) {
            if (in_array($menu['pid'], $ids)) {
                $childIds[] = $menu['id'];
                // 递归获取子级的子级
                $grandChildIds = $this->getAllChildIds($allMenus, [$menu['id']]);
                $childIds = array_merge($childIds, $grandChildIds);
            }
        }

        return array_unique($childIds);
    }

    /**
     * 构建树形结构（你原来的方法）
     */
    private function buildTree($menus, $pid = 0)
    {
        $tree = [];
        foreach ($menus as $menu) {
            if ($menu['pid'] == $pid) {
                $children = $this->buildTree($menus, $menu['id']);
                if ($children) {
                    $menu['children'] = $children;
                }
                $tree[] = $menu;
            }
        }
        return $tree;
    }

    /**
     * 获取扁平菜单列表（用于树形选择器）
     */
    public function flatList(Request $request)
    {
        $param = $request->param();
        if (empty($param['business'])) {
            $business = 'admin';
        } else {
            $business = $param['business'];
        }

        try {
            $menus = Db::name('system_menus')
                ->where('status', 1)->where(['business' => $business])
                ->field('id, title, pid, business, type')
                ->order('sort ASC, id ASC')
                ->select();

            return json([
                'code' => 200,
                'message' => 'success',
                'data' => $menus
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '获取菜单列表失败：' . $e->getMessage()
            ]);
        }
    }

    /**
     * 获取菜单树 - 修复版本
     */
    public function role_tree()
    {
        try {
            $menuModel = new SystemMenus();

            $help = new Help();
            $user = $help->system_user_find();
            $where = "";
            if ($user) {
                if ($user['id'] != '10000') {
                    $role_id = Db::table("system_role")->where(['role_key' => $user['role'], 'system_user_id' => $user['p_id']])->value('id');
                    $menus_ids = $this->getMenuIdsWithParents($role_id, $user['id']);
                    if (count($menus_ids)) {
                        // 匹配所有数字

                        $str = implode(',', $menus_ids);
                        preg_match_all('/\d+/', $str, $matches);

                        $menus_id = implode(',', $matches[0]);

                        if ($menus_id) {
                            $where = "id in ($menus_id)";
                        }
                    }
                }
            }

            $list = Db::table("system_business")->field("system_code id,system_name title")->select();
            foreach ($list as $k => &$v) {
                $business = $v['id'];
                // 获取所有启用的菜单，按模块和排序
                $menus = $menuModel->where('status', 1)->where(['business' => $business])->where($where)
                    ->order('business, sort asc, id asc')
                    ->select()
                    ->toArray();

                // 构建树形结构
                $v['children'] = $this->buildMenuTree($menus, 0);
            }

            return json([
                'code' => 200,
                'message' => 'success',
                'data' => $list
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '服务器错误：' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * 构建菜单树形结构
     */
    private function buildMenuTree(&$menus, $pid)
    {
        $tree = [];

        foreach ($menus as $key => $menu) {
            if ($menu['pid'] == $pid) {
                // 递归构建子节点
                $children = $this->buildMenuTree($menus, $menu['id']);
                if ($children) {
                    $menu['children'] = $children;
                }
                $tree[] = $menu;
            }
        }

        return $tree;
    }

    /**
     * 获取菜单树（按模块分组）
     */
    public function treeByBusiness()
    {
        try {
            $menuModel = new SystemMenus();
            $menus = $menuModel->where('status', 1)
                ->order('business, sort asc, id asc')
                ->select()
                ->toArray();

            // 按模块分组
            $businessGroups = [];
            foreach ($menus as $menu) {
                $business = $menu['business'] ?: 'default';
                if (!isset($businessGroups[$business])) {
                    $businessGroups[$business] = [];
                }
                $businessGroups[$business][] = $menu;
            }

            // 为每个模块构建树
            $result = [];
            foreach ($businessGroups as $business => $businessMenus) {
                $moduleTree = $this->buildMenuTree($businessMenus, 0);
                if ($moduleTree) {
                    $result = array_merge($result, $moduleTree);
                }
            }

            return json([
                'code' => 200,
                'message' => 'success',
                'data' => $result
            ]);

        } catch (\Exception $e) {
            return json([
                'code' => 500,
                'message' => '服务器错误：' . $e->getMessage()
            ], 500);
        }
    }


    //完整的递归解决方案
    public function getMenuIdsWithParents($role_id, $system_user_id = 0)
    {
        // 获取直接菜单ID
        if ($role_id != 2) {
            $direct_menu_ids = Db::table("system_role_menus")
                ->where(['role_id' => $role_id])
                ->column("menu_id");
        } else {
            if ($system_user_id) {
                $direct_menu_ids = Db::table("system_role_menus")
                    ->where(['role_id' => $role_id])->where(['system_user_id' => $system_user_id])
                    ->column("menu_id");
            } else {
                $direct_menu_ids = Db::table("system_role_menus")
                    ->where(['role_id' => $role_id])
                    ->column("menu_id");
            }
        }


        if (empty($direct_menu_ids)) {
            return [];
        }

        $all_menu_ids = $direct_menu_ids;

        // 递归获取所有上级菜单
        $current_level = $direct_menu_ids;
        while (!empty($current_level)) {
            $parents = Db::table("system_menus")
                ->where('id', 'in', $current_level)
                ->where('pid', '>', 0)
                ->column('pid');

            if (empty($parents)) {
                break;
            }

            // 去重并添加到结果中
            $new_parents = array_diff($parents, $all_menu_ids);
            $all_menu_ids = array_merge($all_menu_ids, $new_parents);
            $current_level = $new_parents;
        }

        return $all_menu_ids;
    }


    //模块
    public function select_system()
    {
        $list = Db::table("system_business")->field("system_code value,system_name label")->select();
        return json([
            'code' => 200,
            'message' => 'success',
            'data' => $list
        ]);
    }


    /**
     * 获取验证器
     */
    private function getValidate()
    {
        $rule = [
            'business' => 'require|max:50',
            'title' => 'require|max:20',
            'pid' => 'require|number',
            'type' => 'require|in:directory,menu,button',
            'is_link' => 'require|boolean',
            'link_url' => 'max:50',
            'link_param' => 'max:50',
            'components_url' => 'max:50',
            'permission' => 'max:50',
            'cache_status' => 'require|in:1,2',
            'sort' => 'number',
            'status' => 'require|in:1,2'
        ];

        $message = [
            'business.require' => '所属模块不能为空',
            'business.max' => '所属模块长度不能超过50',
            'title.require' => '菜单名称不能为空',
            'title.max' => '菜单名称长度不能超过20',
            'pid.require' => '父级菜单不能为空',
            'pid.number' => '父级菜单格式不正确',
            'type.require' => '菜单类型不能为空',
            'type.in' => '菜单类型值不正确',
            'is_link.require' => '是否外链不能为空',
            'is_link.boolean' => '是否外链值不正确',
            'link_url.max' => '路由地址长度不能超过50',
            'link_param.max' => '路由参数长度不能超过50',
            'components_url.max' => '组件路径长度不能超过50',
            'permission.max' => '权限标识长度不能超过50',
            'cache_status.require' => '缓存状态不能为空',
            'cache_status.in' => '缓存状态值不正确',
            'sort.number' => '排序必须是数字',
            'status.require' => '显示状态不能为空',
            'status.in' => '显示状态值不正确'
        ];

        return Validate::make($rule, $message);
    }

    //菜单路由
    public function routeMenu(Request $request)
    {
        $param = $request->param();
        if ($param) {
            $params = $param['params'] ?? [];
        }

        if (empty($params['business'])) {
            $params['business'] = 'admin';
        }

        $where = [];
        if (!empty($params['business'])) {
            $where[] = ['business', 'like', '%' . $params['business'] . '%'];
        }

        $list = Db::table("system_menus")->where("type !='button'")->where($where)->select();

        $help = new Help();
        $system_user_id = $help->system_user();

        return json([
            'code' => 200,
            'message' => 'success',
            'system_user_id' => $system_user_id,
            'data' => $this->buildRouteMenu($list,$system_user_id)
        ]);
    }


    //菜单生成路由
    public function buildRouteMenu($data,$system_user_id = 10000)
    {
        // 按 pid 分组
        $grouped = [];

        $menu_ids = [];
        if($system_user_id!=10000){
            $str = implode(",",Db::table("system_role_menus")->where(['system_user_id'=>$system_user_id])->column("menu_id")??[]);
            // 匹配所有数字
            preg_match_all('/\d+/', $str, $matches);
            $menu_ids = explode(',',implode(',', $matches[0]));
        }

        foreach ($data as $item) {
            if($system_user_id!=10000){
                if(!in_array($item['id'],$menu_ids)){
                    $item['status'] = 2;
                }
            }
            $grouped[$item['pid']][] = $item;
        }

        $generateMappings = $this->generateMappings($data);
        // 路径映射配置
        $pathMapping = $generateMappings['pathMapping'];

        // 名称映射配置
        $nameMapping = $generateMappings['nameMapping'];



        function getBuildTree($pid, $grouped, $pathMapping, $nameMapping, $parentPath = '')
        {
            $result = [];
            if (!isset($grouped[$pid])) {
                return $result;
            }

            foreach ($grouped[$pid] as $item) {
                $mappedPath = $pathMapping[$item['title']] ?? '';
                $mappedName = $nameMapping[$item['title']] ?? ucfirst(str_replace(' ', '', $item['title']));

                if ($item['status'] == 1) {
                    $status = true;
                } else {
                    $status = false;
                }

                if ($item['cache_status'] == 1) {
                    $cache_status = true;
                } else {
                    $cache_status = false;
                }

                if ($item['type'] === 'directory') {
                    // 目录节点
                    $node = [
                        'path' => $mappedPath ?: ('/' . strtolower(str_replace(' ', '_', $item['title']))),
                        'name' => $mappedName,
                        'meta' => [
                            'title' => $item['title'],
                            'icon' => $item['icon'],
                            'hidden' => $status,
                            'requiresAuth' => true,
                            'keepAlive' => $cache_status,
                        ]
                    ];

                    $children = getBuildTree($item['id'], $grouped, $pathMapping, $nameMapping, $node['path']);
                    if (!empty($children)) {
                        $node['children'] = $children;
                    }
                } else {
                    // 菜单节点
                    $node = [
                        'path' => $mappedPath ?: strtolower(str_replace(' ', '_', $item['title'])),
                        'name' => $mappedName,
                        'meta' => [
                            'title' => $item['title'],
                            'icon' => $item['icon'],
                            'keepAlive' => $cache_status,
                            'requiresAuth' => true,
                            'hidden' => $status
                        ]
                    ];
                }

                $result[] = $node;
            }

            return $result;
        }

        return [
            'path' => '/',
            'redirect' => '/dashboard',
            'children' => getBuildTree(0, $grouped, $pathMapping, $nameMapping),
        ];
    }

    //处理数组
    public function generateMappings($data)
    {
        $pathMapping = [];
        $nameMapping = [];

        foreach ($data as $item) {
            $title = $item['title'];
            $componentUrl = $item['components_url'];

            // 路径映射直接使用原始数据
            $pathMapping[$title] = $componentUrl;

            // 名称映射：将中文转换为英文名称
            $nameMapping[$title] = $this->formatComponentName($componentUrl);
        }

        return [
            'pathMapping' => $pathMapping,
            'nameMapping' => $nameMapping
        ];
    }

    //处理组件名称
    public function formatComponentName($str)
    {
        // 1. 过滤左侧斜杠
        $str = ltrim($str, '/');

        // 2. 下划线转驼峰
        $str = str_replace('_', ' ', $str);
        $str = ucwords($str);
        $str = str_replace(' ', '', $str);

        return $str;
    }

}